using Ionic.Zip;
using Pdf2epub.Model;
using System.Collections.Generic;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Xml;

namespace Pdf2epub.BusinessLogic.Extractors
{
    internal class GalileoOpenBookOutlineExtraction
    {
        public Chapter[] ExtractChapters(ZipEntry[] zipEntries)
        {
            List<Chapter> topLevelChapters = new List<Chapter>();
            foreach (ZipEntry zipEntry in zipEntries)
            {
                topLevelChapters.AddRange(ExtractHeadersFromFile(zipEntry));
            }
            return topLevelChapters.ToArray();
        }

        private int DetermineHeaderLevel(string hederTagName)
        {
            string levelNumberAsText = hederTagName.Substring(1);
            return int.Parse(levelNumberAsText, CultureInfo.InvariantCulture);
        }

        private IEnumerable<Chapter> ExtractHeadersFromFile(ZipEntry zipEntry)
        {
            List<Chapter> topLevelChapters = new List<Chapter>();

            string htmlContent = GalileoOpenBookExtractor.GetZipFileTextContent(zipEntry);
            XmlNode xmlHtml = GalileoOpenBookExtractor.CreateXmlNodeFromHtml(htmlContent);
            if (xmlHtml == null)
                return new Chapter[] { };
            IEnumerable<XmlNode> headerNodes = GalileoOpenBookExtractor.FindNodesBelow(xmlHtml.ChildNodes, TestIsHeaderNode);

            Chapter[] currentChapters = new Chapter[7];
            foreach (XmlNode headerNode in headerNodes)
            {
                int headerLevel = DetermineHeaderLevel(headerNode.Name);
                if ((headerLevel < 1) || (headerLevel > 6))
                {
                    continue;
                }

                Chapter parentChapter = currentChapters[headerLevel - 1];
                Chapter newChapter = new Chapter(parentChapter, headerNode.InnerText);

                currentChapters[headerLevel] = newChapter;

                if (newChapter.ParentChapter == null)
                {
                    topLevelChapters.Add(newChapter);
                }
                else
                {
                    parentChapter.SubChapters.Add(newChapter);
                }
            }
            return topLevelChapters;
        }

        private bool TestIsHeaderNode(XmlNode node)
        {
            Regex headerRegex = new Regex("h[0-9]");
            return headerRegex.IsMatch(node.Name);
        }
    }
}